﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Froggy.Stocks
{
    public struct Candle
    {
        private double _HighBody;
        private double _LowerBody;
        private double _UpperShadow;
        private double _LowerShadow;
        private double _SizeOfBody;
        private double _SizeOfUpperShadow;
        private double _SizeOfLowerShadow;
        private CandleDirection _Direction;

        private IQuotationSnapshot _QuotationSnapshot;

        /// <summary>
        /// High value of body
        /// </summary>
        public double HighBody
        {
            get { return _HighBody; }
            set { _HighBody = value; }
        }

        /// <summary>
        /// Low value of body
        /// </summary>
        public double LowerBody
        {
            get { return _LowerBody; }
            set { _LowerBody = value; }
        }

        /// <summary>
        /// Size of upper shadow of the candle
        /// </summary>
        public double UpperShadow
        {
            get { return _UpperShadow; }
            private set { _UpperShadow = value; }
        }

        /// <summary>
        /// Size of lower shadow of the candle
        /// </summary>
        public double LowerShadow
        {
            get { return _LowerShadow; }
            private set { _LowerShadow = value; }
        }

        /// <summary>
        /// Size of body of the candle
        /// </summary>
        public double SizeOfBody
        {
            get { return _SizeOfBody; }
            private set { _SizeOfBody = value; }
        }

        /// <summary>
        /// Size of upper shadow of the candle
        /// </summary>
        public double SizeOfUpperShadow
        {
            get { return _SizeOfUpperShadow; }
            private set { _SizeOfUpperShadow = value; }
        }

        /// <summary>
        /// Size of the lower shadow of the candle
        /// </summary>
        public double SizeOfLowerShadow
        {
            get { return _SizeOfLowerShadow; }
            private set { _SizeOfLowerShadow = value; }
        }

        /// <summary>
        /// Indicates the direction type of the candle in the current period
        /// </summary>
        public CandleDirection Direction
        {
            get { return _Direction; }
            private set { _Direction = value; }
        }

        /// <summary>
        /// Snapshot of prices in the period interval
        /// </summary>
        public IQuotationSnapshot QuotationSnapshot
        {
            get { return _QuotationSnapshot; }
            private set { _QuotationSnapshot = value; }
        }

        internal Candle(IQuotationSnapshot qs) : this()
        {
            InitCandle(qs);
        }

        internal void InitCandle(IQuotationSnapshot qs)
        {
            QuotationSnapshot = qs;
            InitCandleDirection(qs);
            InitCandleValues(qs);
            SizeOfUpperShadow = Math.Abs(qs.MaxValue - HighBody);
            SizeOfLowerShadow = Math.Abs(qs.MinValue - LowerBody);
        }

        private void InitCandleDirection(IQuotationSnapshot q)
        {
            if (q.CloseValue == q.OpenValue)
            {
                Direction = CandleDirection.Equal;
            }
            else if (q.CloseValue > q.OpenValue)
            {
                Direction = CandleDirection.Higher;
            }
            else if (q.CloseValue < q.OpenValue)
            {
                Direction = CandleDirection.Lower;
            }
        }

        private void InitCandleValues(IQuotationSnapshot q)
        {
            switch (Direction)
            {
                case CandleDirection.Equal:
                    HighBody = q.CloseValue;
                    LowerBody = q.OpenValue;
                    SizeOfBody = q.CloseValue - q.OpenValue;
                    LowerShadow = q.OpenValue - q.MinValue;
                    UpperShadow = q.MaxValue - q.CloseValue;
                    break;
                case CandleDirection.Higher:
                    HighBody = q.CloseValue;
                    LowerBody = q.OpenValue;
                    SizeOfBody = q.CloseValue - q.OpenValue;
                    LowerShadow = q.OpenValue - q.MinValue;
                    UpperShadow = q.MaxValue - q.CloseValue;
                    break;
                case CandleDirection.Lower:
                    HighBody = q.OpenValue;
                    LowerBody = q.CloseValue;
                    SizeOfBody = q.OpenValue - q.CloseValue;
                    LowerShadow = q.OpenValue - q.MinValue;
                    UpperShadow = q.MaxValue - q.CloseValue;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}